import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators'
import { login, logout, getUserAuthed } from '@/api/users/users'
import { getToken, setToken, removeToken } from '@/utils/cookies'
import store from '@/store'
// import { CaptchaChallenge } from '@/api/captcha'

export interface UserState {
  token: string;
  name: string;
  avatar: string;
  introduction: string;
  roles: string[];
  email: string;
}

@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements UserState {
  public token = getToken() || ''
  public id = ''
  public name = ''
  public avatar = ''
  public introduction = ''
  public roles: string[] = []
  public email = ''

  @Mutation
  private SET_TOKEN (token: string) {
    this.token = token
  }

  @Mutation
  private SET_ID (id: string) {
    this.id = id
  }

  @Mutation
  private SET_NAME (name: string) {
    this.name = name
  }

  @Mutation
  private SET_AVATAR (avatar: string) {
    this.avatar = avatar
  }

  @Mutation
  private SET_INTRODUCTION (introduction: string) {
    this.introduction = introduction
  }

  @Mutation
  private SET_ROLES (roles: string[]) {
    this.roles = roles
  }

  @Mutation
  private SET_EMAIL (email: string) {
    this.email = email
  }

  @Mutation
  private CLEAR_ALL () {
    this.token = ''
    this.id = ''
    this.name = ''
    this.avatar = ''
    this.introduction = ''
    this.roles = []
    this.email = ''
  }

  @Action({ rawError: true })
  public async Login (context: {
    username: string;
    password: string;
    // captchaKey: string;
    // captchaValue: string;
  }) {
    let { username, password } = context
    username = username.trim()
    // const captchaChallenger = new CaptchaChallenge(context.captchaKey, context.captchaValue)
    // const { data } = await login({ username, password }, captchaChallenger)
    const { data } = await login({ username, password })
    setToken(data.accessToken)

    this.SET_TOKEN(data.accessToken)
    this.GetUserInfo()
  }

  @Action
  public ResetToken () {
    removeToken()
    this.SET_TOKEN('')
    this.SET_ROLES([])
  }

  @Action
  public async GetUserInfo () {
    if (this.token === '') {
      throw Error('GetUserInfo: token is undefined!')
    }
    const { data } = await getUserAuthed()
    if (!data) {
      throw Error('Verification failed, please Login again.')
    }
    const { id, roles, username, avatar, introduction, email } = data
    // roles must be a non-empty array
    if (!roles || roles.length <= 0) {
      throw Error('GetUserInfo: roles must be a non-null array!')
    }
    this.SET_ID(`${id}`)
    this.SET_ROLES(roles)
    this.SET_NAME(username)
    this.SET_AVATAR(avatar as string)
    this.SET_INTRODUCTION(introduction)
    this.SET_EMAIL(email)
  }

  @Action
  public async LogOut () {
    if (this.token === '') {
      throw Error('LogOut: token is undefined!')
    }
    await logout()
    removeToken()
    this.CLEAR_ALL()
  }
}

export const UserModule = getModule(User)
